/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFServer
  \brief client for communication among different hosts on the Internet
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2023-06-21
  \date 2023-06-25 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                    </tr>
  <tr>  <td>2023-06-21   <td>Asia Sun    <td>file created                   </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <iostream>
#include <unistd.h> // for compatibility with older linux versions
#include "ETFServer.h"
#include "ETFQueue.h"
#include "ETFReadShm.h"
#include "ETFMsg.h"

using std::cout;
using std::endl;

ETFServer::ETFServer() : ETFVServer(){}

/// create server with ip:port
ETFServer::ETFServer(const string &ip, short port, const string &shm, DaqType type,
int nshm) : ETFVServer(ip, port, type), fNShm(nshm){
  if(!ETFReadShm::exist(shm)){
    ETFMsg::Warn("ETFServer", "ctor: shm %s non-exist", shm.data());
    exit(1);
  } // end else
  else{
    fShm0 = new ETFReadShm(shm, type);
    fQueue = fShm0->queue();
    // porting out to an shm for others to use //
    char shm1[128]{};
    for(int i = 0; i < fNShm; i++){
      sprintf(shm1, "etfanaS_%s%d", type == kPXI ? "pxi" : "vme", i);
      fShms.push_back(new ETFReadShm(shm1, type, true)); // true: create shm
    } // end for over shms
  } // end else
} // end of ctor

ETFServer::~ETFServer(){
  Close();
} // end dtor

// send to the other end of the Internet
void ETFServer::send(){
  while(!fQueue->Pop(fdc)) usleep(10);
  for(auto &p : fShms) p->write(fQueue->ItemOut()->buf);

  static time_t t0; // in ms
  if(ETFMsg::ms() - t0 > 1000){
    t0 = ETFMsg::ms();
    cout << "ETFServer: ";
    cout << (daqType() == kPXI ? "PXI" : "VME");
    cout << " load: " << fQueue->NLoaded() << " empty: " << fQueue->NEmpty();
    cout << " tcp: " << ETFQueue::sockStateC(fdc);
    cout << " " << ETFMsg::sec() % 100 << endl;
  } // end if
} // end member function send

// init the online_shm of the daq to the initial state
void ETFServer::InitDaqShm(){
  if(fShm0) fShm0->InitShm(true); // true: reset the readShm's queue together
  else ETFMsg::Warn("ETFServer", "InitDaqShm: fShm0 not assigned");
  for(auto &p : fShms) if(p) p->InitShm(true);
} // end member function InitDaqShm

void ETFServer::Close(){
  for(auto &p : fShms) if(p){ delete p; p = nullptr; }
} // end member function Close
